#ifndef __CGE_VECTOR2_H__
#define __CGE_VECTOR2_H__

#include "cgeCommons.h"
#include "cgeMath.h"

namespace cge
{
	namespace std
	{
		template<class TVal>
		class Vector2
		{
		public:
			Vector2()
			{
				Set(0, 0);
			}
			
			Vector2(const Vector2& sz)
			{
				Set(sz.X, sz.Y);
			}

			Vector2(TVal x, TVal y)
			{
				Set(x, y);
			}

			void Set(TVal x, TVal y)
			{
				X = x;
				Y = y;
			}

			f32 Length() const
			{
				return Math::Sqrt(X * X + Y * Y);
			}

			f32 Dot(const Vector2& v2) const
			{
				return (X * v2.X + Y * v2.Y);
			}

			f32 AngleBetween(const Vector2& v2) const
			{
				return Math::Acos(Dot(v2));
			}

			void Normalize()
			{
				f32 len = Length();
				X /= len;
				Y /= len;
			}

			template<class TArg>
			Vector2 operator * (TArg scalar) const
			{
				return Vector2(X * scalar, Y * scalar);
			}

			template<class TArg>
			Vector2 operator / (TArg scalar) const
			{
				return Vector2(X / scalar, Y / scalar);
			}

			Vector2 operator - (void) const
			{
				return Vector2(-X, -Y);
			}

			friend Vector2 operator + (const Vector2& lsz, const Vector2& rsz)
			{
				return Vector2(lsz.X + rsz.X , lsz.Y + rsz.Y);
			}

			friend Vector2 operator - (const Vector2& lsz, const Vector2& rsz)
			{
				return Vector2(lsz.X - rsz.X , lsz.Y - rsz.Y);
			}

			friend b8 operator == (const Vector2& lsz, const Vector2& rsz)
			{
				return (lsz.X == (TVal)rsz.X) && (lsz.Y == (TVal)rsz.Y);
			}
			
			friend b8 operator != (const Vector2& lsz, const Vector2& rsz)
			{
				return (lsz.X != (TVal)rsz.X) || (lsz.Y != (TVal)rsz.Y);
			}

			template<class TArg>
			Vector2& operator *= (TArg scalar)
			{
				X *= scalar;	Y *= scalar; 
				return *this;
			}

			template<class TArg>
			Vector2& operator /= (TArg scalar)
			{
				X /= scalar;	Y /= scalar; 
				return *this;
			}

			Vector2& operator += (const Vector2& sz)
			{
				X += sz.X;		Y += sz.Y;
				return *this;
			}

			Vector2& operator -= (const Vector2& sz)
			{
				X -= sz.X;		Y -= sz.Y;
				return *this;
			}

			Vector2& operator = (const Vector2& sz)
			{
				Set(sz.X, sz.Y);
				return *this;
			}

		public:
			union
			{
				struct { TVal X, Y; };
				TVal Coords[2];
			};
		};

		typedef Vector2<s32> Vector2s;

		typedef Vector2<u32> Vector2u;

		typedef Vector2<f32> Vector2f;

		typedef Vector2<f64> Vector2d;
	}
}

#endif//__CGE_VECTOR2_H__